#include "../source/sylar.h"
#include <iostream>

static int sock_listen_fd = -1;
void test_accept();

void error(char *msg)
{
    perror(msg);
    std::cout << "erreur..." << std::endl;
    exit(1);
}

void watch_io_read()
{
    IOManager::GetThis()->addEvent(sock_listen_fd, IOManager::READ, test_accept);
}

void test_accept()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int fd = accept(sock_listen_fd, (struct sockaddr *)&addr, &len);
    if (fd < 0)
    {
        std::cout << "fd = " << fd << " accept false" << std::endl;
    }
    else
    {
        fcntl(fd, F_SETFL, O_NONBLOCK);
        IOManager::GetThis()->addEvent(fd, IOManager::READ, [fd]()
                                       {
            char buf[1024];
            memset(&buf,0,sizeof(buf));
            for(;;)
            {
                int ret = recv(fd,buf,sizeof(buf),0);
                if(ret <= 0)
                {
                    if(errno == EAGAIN) continue;
                    close(fd);
                    break;
                }
                else
                {
                    ret = send(fd,buf,ret,0);
                }
            } });
    }
    std::cout << IOManager::GetThis() << std::endl;
    IOManager::GetThis()->schedule(watch_io_read);
}

void test_iomanager()
{
    int portno = 8080;
    struct sockaddr_in server_addr, client_addr;
    sock_listen_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_listen_fd < 0)
    {
        error("create socket error...\n");
    }

    int value = 1;
    setsockopt(sock_listen_fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value));

    memset((char *)&server_addr, 0, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(portno);
    server_addr.sin_addr.s_addr = INADDR_ANY;

    if (bind(sock_listen_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        error("bind socket error...\n");
    }

    if (listen(sock_listen_fd, 1024) < 0)
    {
        error("listening error...\n");
    }

    std::cout << "epoll echo server listening for connections on port : " << portno << std::endl;
    fcntl(sock_listen_fd, F_SETFL, O_NONBLOCK);

    IOManager iom;
    iom.addEvent(sock_listen_fd, IOManager::READ, test_accept);
}

int main()
{
    test_iomanager();
    return 0;
}